package com.logic.modular.game.player.match.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.comment.exception.ServiceException;

import com.logic.comment.util.Node;
import com.logic.comment.util.RedisUtils;
import com.logic.comment.util.XSThreadUtil;
import com.logic.comment.util.XsRedisUtils;
import com.logic.config.netty.web.service.MessageService;
import com.logic.modular.game.RankMove;
import com.logic.modular.game.battle.info.base.PvpPlayerInfo;
import com.logic.modular.game.battle.info.base.PvpPlayerInfoServiceImpl;
import com.logic.modular.game.core.mapper.PvpRanksMapper;
import com.logic.modular.game.player.bag.service.BagItemServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType1ServiceImpl;
import com.logic.modular.game.player.bag.service.PlayerPropType2ServiceImpl;
import com.comment.pojo.domain.logic.domain.PlayerHero;
import com.comment.pojo.domain.logic.domain.PvpRanks;
import com.logic.modular.game.player.hero.service.PlayerHeroServiceImpl;

import com.logic.modular.game.player.info.service.PlayerStatusServiceImpl;
import com.logic.modular.game.PvpCity;
import com.logic.modular.gameCore.config.service.impl.CoreConfigServiceImpl;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.logic.modular.game.GameConstant.PVP_MATCH_RANK_MOVE_KEY;
import static com.logic.modular.game.GameConstant.PvpRanksCacheKey;

/**
 * 武将队伍(PvpRanks)表服务实现类
 *
 * @author cxy
 * @since 2024-07-18 11:19:32
 */
@Validated
@Slf4j
@Service
public class PvpRanksServiceImpl extends ServiceImpl<PvpRanksMapper, PvpRanks> implements PvpRanksService {
    @Resource
    private PlayerHeroServiceImpl heroService;
    @Resource
    private PvpCityServiceImpl pvpCityServiceImpl;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private PlayerStatusServiceImpl playerStatusServiceImpl;
    @Resource
    private PlayerPropType2ServiceImpl playerPropType2ServiceImpl;
    @Resource
    private BagItemServiceImpl bagItemServiceImpl;
    @Resource
    private PvpPlayerInfoServiceImpl pvpPlayerInfoServiceImpl;
    @Resource
    private PlayerPropType1ServiceImpl playerPropType1ServiceImpl;
    @Resource
    private PlayerHeroServiceImpl playerHeroServiceImpl;
    @Resource
    private XsRedisUtils xsRedisUtils;

    public Map<String, PvpRanks> mapCache(Long playerId) {
        String format = String.format(PvpRanksCacheKey, playerId);
        return xsRedisUtils.hGetAllBean(format, PvpRanks.class);
    }

    public List<PvpRanks> list(Long playerId) {
        List<PvpRanks> ranksList;
        Map<String, PvpRanks> stringPvpRanksMap = mapCache(playerId);
        if (stringPvpRanksMap == null || stringPvpRanksMap.isEmpty()) {
            ranksList = super.list(new LambdaQueryWrapper<PvpRanks>().eq(PvpRanks::getUid, playerId));
        } else {
            ranksList = new ArrayList<>(stringPvpRanksMap.values());
        }
        return ranksList;
    }

    public PvpRanks select(
            Long playerId, Integer ranksNo
    ) {
        String key1 = String.format(PvpRanksCacheKey, playerId);
        String key2 = ranksNo.toString();
        PvpRanks pvpRank = xsRedisUtils.hGetBean(key1, key2, PvpRanks.class);
        if (pvpRank == null) {
            pvpRank = super.getOne(new LambdaQueryWrapper<PvpRanks>().eq(PvpRanks::getUid, playerId)
                    .eq(PvpRanks::getRankNo, ranksNo)
            );
            xsRedisUtils.hSet(key1, key2, pvpRank, 60, TimeUnit.MINUTES);
        }
        return pvpRank;
    }

    @Override
    public boolean updateById(PvpRanks entity) {
        boolean b = super.updateById(entity);
        if (b) {
            PvpRanks byId = super.getById(entity.getId());
            xsRedisUtils.hSet(String.format(PvpRanksCacheKey, byId.getUid()), byId.getRankNo().toString(), byId);
        }
        MessageService.sendMessageToUser(entity.getUid(), MessageService.updateJsonObject("pvpRanks", entity));
        return b;
    }

    @Override
    public boolean save(PvpRanks entity) {
        boolean save = super.save(entity);
        if (save) {
            xsRedisUtils.hSet(String.format(PvpRanksCacheKey, entity.getUid()), entity.getRankNo().toString(), entity, 60, TimeUnit.MINUTES);
        }
        return save;
    }

    public List<PvpRanks> obtainPvpRanKs(Long playerId) {
        List<PvpRanks> ranksList = list(playerId);
        if (ranksList.isEmpty()) {
            ranksList = super.list(new LambdaQueryWrapper<PvpRanks>().eq(PvpRanks::getUid, playerId));
            if (ranksList.isEmpty() || ranksList.size() < 5) {
                for (int i = 0; i < 5; i++) {
                    PvpRanks select = select(playerId, i + 1);
                    if (select == null) {
                        PvpRanks pvpRanks = new PvpRanks();
                        pvpRanks.setUid(playerId);
                        pvpRanks.setRankNo((i + 1));
                        save(pvpRanks);
                        ranksList.add(pvpRanks);
                    }
                }
            }
        }
        return ranksList;
    }


    public List<PvpRanks> formation(
            Long playerId,
            Integer rankNo,
            Long heroId1,
            Long heroId2,
            Long heroId3
    ) {
        List<Long> heroes = Arrays.asList(heroId1, heroId2, heroId3);
        for (Long heroId : heroes) {
            if (heroId != null && heroId != 0) {
                PlayerHero select = heroService.select(playerId, heroId);
                if (select == null) {
                    throw new ServiceException("武将" + heroes + "不存在");
                }
            }
        }

        List<PvpRanks> ranksList = obtainPvpRanKs(playerId);
        List<PvpRanks> collect = ranksList.stream()
                .filter(item -> item.getStatus() == 2)
                .collect(Collectors.toList());

        if (collect.stream().anyMatch(item -> {
            Set<Long> heroIds = item.obtainCoreHeroIds();
            return heroIds.contains(heroId1) || heroIds.contains(heroId2) || heroIds.contains(heroId3);
        })) {
            throw new ServiceException("存在战斗中的武将");
        }

        long force = 0;
        for (PlayerHero playerHero : getWuJiang(playerId, rankNo)) {
            force += playerHero.getCurrentForce();
            playerHero.setCurrentForce(0L);
            heroService.updateById(playerHero);
        }

        PvpRanks select = select(playerId, rankNo);
        Long currentMatchId = playerStatusServiceImpl.get(playerId).getCurrentMatchId();
        Long cityId = select.getCityId();
        if (cityId != 0) {
            PvpCity pvpCity = pvpCityServiceImpl.getPvpCity(cityId, currentMatchId);
            pvpCity.setReadyArmy(pvpCity.getReadyArmy() + force);
        }

        return ranksList.stream().peek(item -> {
            if (Objects.equals(item.getRankNo(), rankNo)) {
                item.setHeroId1(heroId1);
                heroService.updateRankOrder(playerId, heroId1, 1);
                item.setHeroId2(heroId2);
                heroService.updateRankOrder(playerId, heroId2, 2);
                item.setHeroId3(heroId3);
                heroService.updateRankOrder(playerId, heroId3, 3);
            } else {
                if (heroes.contains(item.getHeroId1())) {
                    item.setHeroId1(0L);
                }
                if (heroes.contains(item.getHeroId2())) {
                    item.setHeroId2(0L);
                }
                if (heroes.contains(item.getHeroId3())) {
                    item.setHeroId3(0L);
                }
                item.setStatus(1);
            }
            updateById(item);
        }).sorted(Comparator.comparing(PvpRanks::getRankNo)).collect(Collectors.toList());
    }


    public List<PvpRanks> formation2(
            Long playerId, Integer rankNo, Long[][] rankInfo
    ) {
        PvpRanks pvpRanks = select(playerId, rankNo);
        formationCheckRanks(pvpRanks);

        Long[] longs = pvpRanks.obtainRankInfo();

        for (int i = 0; i < 3; i++) {
            int targetRanksOrder = i + 1;
            long currentPositHero = longs[i];

            long targetCoreHeroId = rankInfo[i][0];
            long targetForce = rankInfo[i][1];

            if (currentPositHero == 0 && targetCoreHeroId == 0) {
                continue;
            }

            if (targetCoreHeroId == 0 && !Objects.equals(currentPositHero, targetCoreHeroId)) {// 进行卸队
                uninstallation(playerId, rankNo, new int[]{targetRanksOrder});
            }

            PlayerHero playerHero = heroService.select(playerId, targetCoreHeroId);
            formatCheckHero(rankNo, playerHero);
            playerHero.setRankNo(rankNo);
            playerHero.setRankOrder(targetRanksOrder);
            heroService.updateById(playerHero);

            // 队伍变动
            formatRanksOrder(targetRanksOrder, pvpRanks, targetCoreHeroId);
            // 兵力变动
            if (playerHero.getCurrentForce() != targetForce) {
                playerHeroServiceImpl.buBing(playerId, targetCoreHeroId, targetForce);
            }
        }
        updateById(pvpRanks);
        return obtainPvpRanKs(playerId);
    }

    private static void formatRanksOrder(
            int targetRanksOrder, PvpRanks select, long coreHeroId
    ) {
        if (targetRanksOrder == 1) {
            select.setHeroId1(coreHeroId);
        } else if (targetRanksOrder == 2) {
            select.setHeroId2(coreHeroId);
        } else if (targetRanksOrder == 3) {
            select.setHeroId3(coreHeroId);
        } else {
            throw new ServiceException("不支持的队伍位置");
        }
    }


    private void formationCheckRanks(PvpRanks select) {
        if (select == null) {
            throw new ServiceException("当前队伍不存在");
        }
        Integer status = select.getStatus();
        if (status == null) {
            status = 0;
            select.setStatus(status);
        }
        if (status == 2) {
            throw new ServiceException("战斗中");
        }
        if (status == 3) {
            throw new ServiceException("移动中");
        }
    }

    private void formatCheckHero(Integer rankNo, PlayerHero playerHero) {
        if (playerHero == null) {
            throw new ServiceException("武将不存在");
        }
        Long uid = playerHero.getUid();
        Integer playerHeroRankNo = playerHero.getRankNo();
        if (playerHeroRankNo == null) {
            playerHeroRankNo = 0;
            playerHero.setRankNo(playerHeroRankNo);
        }
        if (!playerHeroRankNo.equals(rankNo) && playerHeroRankNo != 0) {
            // 校验数据
            PvpRanks select = select(uid, playerHeroRankNo);
            if (select.obtainCoreHeroIds().contains(playerHero.getCoreHeroId())) {
                throw new ServiceException(String.format("目标%d不在指定队伍(%d),当前英雄所处队伍(%d),请先卸队", playerHero.getCoreHeroId(), rankNo, playerHeroRankNo));
            }
            // 存在缓存问题,开始清空
            playerHero.clear();
            heroService.updateById(playerHero);
        }
    }

    public PvpRanks uninstallation(
            Long playerId,
            int rankNo,
            int[] rankOrder
    ) {
        Long currentMatchId = playerStatusServiceImpl.get(playerId).getCurrentMatchId();
        if (currentMatchId < 1) {
            throw new ServiceException("当前不在对局中");
        }

        PvpRanks pvpRanks = select(playerId, rankNo);
        if (pvpRanks.getStatus() != 1 && pvpRanks.getCityId() != 0) {
            throw new ServiceException("当前队伍状态异常");
        }

        if (rankOrder.length == 0) {
            return pvpRanks;
        }

        long force = 0;
        for (int order : rankOrder) {
            Long coreHeroId = null;
            if (order == 1) {
                coreHeroId = pvpRanks.getHeroId1();
                pvpRanks.setHeroId1(0L);
            } else if (order == 2) {
                coreHeroId = pvpRanks.getHeroId2();
                pvpRanks.setHeroId2(0L);
            } else if (order == 3) {
                coreHeroId = pvpRanks.getHeroId3();
                pvpRanks.setHeroId3(0L);
            }
            if (coreHeroId != null && coreHeroId != 0) {
                PlayerHero playerHero = playerHeroServiceImpl.select(playerId, coreHeroId);
                playerHero.setRankNo(0);
                playerHero.setRankOrder(0);
                force += playerHero.getCurrentForce();
                playerHero.setCurrentForce(0L);
                heroService.updateById(playerHero);

                updateById(pvpRanks);
            }
        }


        PvpCity playerCity = pvpCityServiceImpl.getPlayerCity(playerId, pvpRanks.getCityId(), currentMatchId);
        playerCity.setReadyArmy(playerCity.getReadyArmy() + force);
        pvpCityServiceImpl.update(playerCity);

        return pvpRanks;
    }

    public PvpRanks teamPositionEditing(Long playerId, int rankNo, int[] rankOrder) {
        PvpRanks select = select(playerId, rankNo);
        Long[] heroIds = new Long[]{select.getHeroId1(), select.getHeroId2(), select.getHeroId3()};
        for (int index = 0; index < rankOrder.length; index++) {
            Long heroId = heroIds[rankOrder[index] - 1];
            if (index == 0) {
                select.setHeroId1(heroId);
            }
            if (index == 1) {
                select.setHeroId2(heroId);
            }
            if (index == 2) {
                select.setHeroId3(heroId);
            }
            PlayerHero playerHero = playerHeroServiceImpl.select(playerId, heroId);
            playerHero.setRankNo(rankNo);
            playerHero.setRankOrder(index + 1);
            heroService.updateById(playerHero);
        }
        updateById(select);
        return select;
    }


    /**
     * 清空pvp队伍
     */
    public void resetPvp(Long playerId) {
        List<PvpRanks> values = obtainPvpRanKs(playerId);
        values.forEach(item -> {
            for (Long coreHeroId : item.obtainCoreHeroIds()) {
                if (coreHeroId != 0) {
                    PlayerHero playerHero = heroService.select(playerId, coreHeroId);
                    playerHero.clear();
                    heroService.updateById(playerHero);
                }
            }
            item.setCityId(0L);
            item.setHeroId1(0L);
            item.setHeroId2(0L);
            item.setHeroId3(0L);
            updateById(item);
        });
    }


    public List<PlayerHero> getWuJiang(Long uid, Integer ranksNo) {
        PvpRanks accountRanks = select(uid, ranksNo);
        return accountRanks.obtainCoreHeroIds().stream().map(item -> heroService.select(uid, item)).collect(Collectors.toList());
    }

    /**
     * 获取当前编队中还活着的武将
     */
    public List<PlayerHero> obtainSurvivingHero(Long uid, Integer ranksNo) {
        return getWuJiang(uid, ranksNo).stream().filter(item ->
                item.getCurrentForce() > 0
        ).collect(Collectors.toList());
    }

    /**
     * 获取队伍当前兵力
     */
    public Long obtainForce(Long uid, Integer ranksNo) {
        return getWuJiang(uid, ranksNo).stream().mapToLong(PlayerHero::getCurrentForce).sum();
    }

    /**
     * 获取城池守军编号
     */
    public List<Integer> obtainCityRanksNoList(Long cityCoreId, Long ownerUid) {
        if (ownerUid < 0) {
            return null;
        }
        return obtainPvpRanKs(ownerUid).stream()
                .filter(item ->
                        item.getCityId().equals(cityCoreId) &&
                                obtainForce(ownerUid, item.getRankNo()) > 0 &&
                                item.getStatus() == 1
                )
                .map(PvpRanks::getRankNo)
                .sorted()
                .collect(Collectors.toList());
    }

    public List<PlayerHero> obtainCityRanksHeroByNo(Long cityCoreId, Long ownerUid, Integer no) {
        if (ownerUid < 0) {
            return null;
        }
        PvpRanks select = select(ownerUid, no);
        if (select.getStatus() == 1 && select.getCityId().equals(cityCoreId)) {
            return select.obtainCoreHeroIds().stream().map(item -> heroService.select(ownerUid, item))
                    .filter(item -> item.getCurrentForce() > 0)
                    .collect(Collectors.toList());
        }
        return null;
    }


    @Resource
    private XSThreadUtil xsThreadUtil;

    public PvpRanks teamMovement(
            Long playerId,
            Integer rankNo,
            Long targetCityId
    ) {
        PvpRanks select = select(playerId, rankNo);
        if (select == null)
            throw new ServiceException("队伍不存在");
        Long startCityId = select.getCityId();

        long sum = getWuJiang(playerId, rankNo).stream().mapToLong(PlayerHero::getCurrentForce).sum();
        long need = sum * 5;
        if (!playerPropType1ServiceImpl.tryPay(playerId, 5L, BigDecimal.valueOf(need))) {
            throw new ServiceException("粮草不足");
        }

        // 获取运输时间
        Node node = pvpCityServiceImpl.bfsOwnerMinPaths(
                playerId, Math.toIntExact(startCityId), Math.toIntExact(targetCityId));
        int needTime = node.getCos();
        node.setRankNo(Math.toIntExact(rankNo));
        node.setPlayerId(playerId);
        MessageService.sendMessageToUser(playerId, MessageService.updateJsonObject("teamMovement", node));

        // 创建线程池
        xsThreadUtil.scheduledExecutorService().schedule(() -> {
            select.setCityId(targetCityId);
            updateById(select);
        }, needTime, TimeUnit.SECONDS);
        return select;
    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class PvpRanksInfo {
        private Integer rankNo;
        List<PlayerHero> ranksHeroList;
    }


    public void tryAttackCity(Long attackPlayerId, Long currentMatchId, Integer attackRanksNo, Long targetCityId) {
        long sum = getWuJiang(attackPlayerId, Math.toIntExact(attackRanksNo)).stream().mapToLong(PlayerHero::getCurrentForce).sum() * 5;
        Map<Long, BigDecimal> propMap = new HashMap<>();
        propMap.put(5L, BigDecimal.valueOf(sum));
        String pledgePropKey = bagItemServiceImpl.pledgeProp(attackPlayerId, propMap, "进攻城池的消耗");
        try {
            tryAttackCityNoPap(attackPlayerId, currentMatchId, attackRanksNo, targetCityId, pledgePropKey);
            bagItemServiceImpl.abandoningPledge(pledgePropKey);
        } catch (Exception e) {
            bagItemServiceImpl.redemptionOfProp(pledgePropKey);
            throw new RuntimeException(e);
        }
    }

    public void tryAttackCityNoPap(Long attackPlayerId, Long currentMatchId, Integer attackRanksNo, Long targetCityId, String pledgePropKey) {
        PvpRanks ranks = select(attackPlayerId, Math.toIntExact(attackRanksNo));
        Long startCityId = ranks.getCityId();

        Integer status = ranks.getStatus();
        if (status == 2) {
            throw new ServiceException("当前队伍未处于战斗中");
        }

        PvpCity targetCity = pvpCityServiceImpl.getCache(currentMatchId, targetCityId);
        if (targetCity == null) {
            throw new ServiceException("目标城池不存在");
        }

        PvpPlayerInfo ownerInfo = pvpPlayerInfoServiceImpl.get(currentMatchId, attackPlayerId);

        Long uid = targetCity.getOwnerUid();
        if (uid != null && uid != 0) {
            PvpPlayerInfo targetCityPlayer = pvpPlayerInfoServiceImpl.get(currentMatchId, uid);
            boolean equals = targetCityPlayer.getAlliesUidList().equals(ownerInfo.getAlliesUidList());
            if (equals) {
                throw new ServiceException("不能攻打友军");
            }
        }


        String key = String.format(PVP_MATCH_RANK_MOVE_KEY, currentMatchId);
        RankMove rankMove = (RankMove) redisUtils.hGet(key, attackPlayerId + "-" + attackRanksNo);
        if (rankMove == null) {
            rankMove = new RankMove();
        }
        rankMove.setRankNo(Math.toIntExact(attackRanksNo));
        rankMove.setPlayerId(attackPlayerId);
        rankMove.setAccelerateNum(0);
        rankMove.setStartCityId(startCityId);
        rankMove.setStartTime(new Date());
        rankMove.setTargetCityId(targetCityId);
        rankMove.setType(1);
        rankMove.setCost(pledgePropKey);

        // // 攻击方城池
        Node node = pvpCityServiceImpl.bfsOwnerMinPaths(
                attackPlayerId,
                Math.toIntExact(startCityId),
                Math.toIntExact(targetCityId)
        );
        node.setRankNo(Math.toIntExact(attackRanksNo));
        node.setPlayerId(attackPlayerId);
        int needTime = node.getCos();
        // // 获取完成时间
        DateTime dateTime = DateUtil.offsetSecond(new Date(), needTime);
        // DateTime dateTime = DateUtil.offsetSecond(new Date(), 1);//测试专用
        rankMove.setEndTime(dateTime);
        rankMove.setEndTimeLong(dateTime.getTime());
        log.info("玩家：{}，的队伍：{}，{}--时会开始攻打城 池", attackPlayerId, attackRanksNo, dateTime);
        redisUtils.hPut(key, attackPlayerId + "-" + attackRanksNo, rankMove, 6 * 60, TimeUnit.SECONDS);
        MessageService.sendMessageToMatch(currentMatchId, MessageService.updateJsonObject("rankMove", rankMove));
        MessageService.sendMessageToMatch(currentMatchId, MessageService.updateJsonObject("node", node));
        ranks.setStatus(3);
        updateById(ranks);
        MessageService.sendMessageToUser(attackPlayerId, MessageService.updateJsonObject("ranks", ranks));
    }

    public void marchingAcceleration(Long playerId, Integer rankNo) {
        Long currentMatchId = playerStatusServiceImpl.currentMatchId(playerId);
        String key1 = String.format(PVP_MATCH_RANK_MOVE_KEY, currentMatchId);

        RankMove rankMove = (RankMove) redisUtils.hGet(key1, playerId + "-" + rankNo);
        if (rankMove == null) {
            throw new ServiceException("未找到对应行军的信息");
        }
        if (rankMove.getEndTime().getTime() - System.currentTimeMillis() <= 0) {
            throw new ServiceException("行军已结束");
        }
        Integer accelerateNum = rankMove.getAccelerateNum();
        if (accelerateNum >= CoreConfigServiceImpl.getCache(1L).getValue1().intValue()) {
            throw new ServiceException("加速次数已用完");
        }

        boolean b = playerPropType2ServiceImpl.tryPayProp(playerId, 2003L, BigDecimal.valueOf(1));
        if (b) {
            try {
                // 行军加速 剩余时间 的一半
                long accelerationTime = DateUtil.between(rankMove.getEndTime(), new Date(), DateUnit.MS) / 2;
                Date endTime = new Date(rankMove.getStartTime().getTime() + accelerationTime);
                rankMove.setEndTime(endTime);
                rankMove.setEndTimeLong(endTime.getTime());
                rankMove.setAccelerationTime(accelerationTime);

                log.info("玩家：{}，的队伍:{}使用了加速券,加速了:{}s,{}:时会开始攻打城池", playerId, rankNo, accelerationTime / 1000.0, endTime);
                redisUtils.hPut(key1, playerId + "-" + rankNo, rankMove, 6 * 60, TimeUnit.SECONDS);
                MessageService.sendMessageToMatch(currentMatchId, MessageService.updateJsonObject("rankMove", rankMove));
            } catch (Exception e) {
                log.error("加速失败", e);
                bagItemServiceImpl.obtainBagItem(playerId, 2003L, BigDecimal.valueOf(1));
                throw new ServiceException("加速失败");
            }
        } else {
            throw new ServiceException("加速券不足");
        }
    }

    /**
     * 援护目标城池
     */
    public Object tryInterveneTargetCity(Long attackPlayerId, Long currentMatchId, Integer attackRanksNo, Long targetCityId) {
        PvpRanks ranks = select(attackPlayerId, Math.toIntExact(attackRanksNo));
        Long startCityId = ranks.getCityId();

        long sum = getWuJiang(attackPlayerId, Math.toIntExact(attackRanksNo)).stream().mapToLong(PlayerHero::getCurrentForce).sum();
        long l = sum * 5;
        if (!playerPropType1ServiceImpl.tryPay(attackPlayerId, 5L, BigDecimal.valueOf(l))) {
            throw new ServiceException("粮食不足");
        }

        Integer status = ranks.getStatus();
        if (status == 2) {
            throw new ServiceException("当前队伍未处于战斗中");
        }
        if (status == 3) {
            throw new ServiceException("当前队伍以出征");
        }
        if (status == 4) {
            throw new ServiceException("当前队伍准备战斗中");
        }

        PvpCity targetCity = pvpCityServiceImpl.getCache(currentMatchId, targetCityId);
        if (targetCity == null) {
            throw new ServiceException("目标城池不存在");
        }

        PvpPlayerInfo ownerInfo = pvpPlayerInfoServiceImpl.get(currentMatchId, attackPlayerId);

        Long uid = targetCity.getOwnerUid();
        if (uid != null && uid != 0) {
            PvpPlayerInfo targetCityPlayer = pvpPlayerInfoServiceImpl.get(currentMatchId, uid);
            boolean equals = targetCityPlayer.getAlliesUidList().equals(ownerInfo.getAlliesUidList());
            if (!equals) {
                throw new ServiceException("不能援护队友以外的城池");
            }
        }


        String key = String.format(PVP_MATCH_RANK_MOVE_KEY, currentMatchId);
        RankMove rankMove = (RankMove) redisUtils.hGet(key, attackPlayerId + "-" + attackRanksNo);
        if (rankMove == null) {
            rankMove = new RankMove();
        }
        rankMove.setRankNo(Math.toIntExact(attackRanksNo));
        rankMove.setPlayerId(attackPlayerId);
        rankMove.setAccelerateNum(0);
        rankMove.setStartCityId(startCityId);
        rankMove.setStartTime(new Date());
        rankMove.setTargetCityId(targetCityId);
        rankMove.setType(2);

        Node node = pvpCityServiceImpl.bfsOwnerMinPaths(
                attackPlayerId,
                Math.toIntExact(startCityId),
                Math.toIntExact(targetCityId)
        );
        int needTime = node.getCos();
        // 获取完成时间
        DateTime dateTime = DateUtil.offsetSecond(new Date(), needTime);
        rankMove.setEndTime(dateTime);
        rankMove.setEndTimeLong(dateTime.getTime());
        log.info("玩家：{}，的队伍：{}，{}--时,到达援护城池", attackPlayerId, attackRanksNo, dateTime);
        redisUtils.hPut(key, attackPlayerId + "-" + attackRanksNo, rankMove, 6 * 60, TimeUnit.SECONDS);
        MessageService.sendMessageToMatch(currentMatchId, MessageService.updateJsonObject("rankMoveIntervene", rankMove));
        ranks.setStatus(3);
        updateById(ranks);
        MessageService.sendMessageToUser(attackPlayerId, MessageService.updateJsonObject("ranks", ranks));
        return ranks;
    }
}
